---
title: ^0.14.0 to ^1.0.0
---

After a long wait, the first stable version of Riverpod is finally released 👏

To see the full list of changes, consult the [Changelog](https://pub.dev/packages/flutter_riverpod/changelog#100).  
In this page, we will focus on how to migrate an existing Riverpod application
from version 0.14.x to version 1.0.0.

## Using the migration tool to automatically upgrade your project to the new syntax

Before explaining the various changes, it is worth noting that Riverpod comes with
a command-line tool to automatically migrate your project for you.

### Installing the command line tool

To install the migration tool, run:

```sh
dart pub global activate riverpod_cli
```

You should now be able to run:

```sh
riverpod --help
```

### Usage

Now that the command line is installed, we can start using it.

- First, open the project you want to migrate in your terminal.
- **Do not** upgrade Riverpod.  
  The migration tool will upgrade the version of Riverpod for you.

  :::danger
  Not upgrading Riverpod is important.  
  The tool will not execute properly if you have already installed version 1.0.0.
  As such, make sure that you are properly using an older version before starting the tool.
  :::

- Make sure that your project does not contain errors.
- Execute:
  ```sh
  riverpod migrate
  ```

The tool will then analyze your project and suggest changes. For example you may see:

```diff
-Widget build(BuildContext context, ScopedReader watch) {
+Widget build(BuildContext context, Widget ref) {
-  MyModel state = watch(provider);
+  MyModel state = ref.watch(provider);
}

Accept change (y = yes, n = no [default], A = yes to all, q = quit)?
```

To accept the change, simply press <kbd>y</kbd>. Otherwise to reject it, press <kbd>n</kbd>.

## The changes

Now that we've seen how to use the CLI to automatically upgrade your project,
let's see in detail the changes necessary.

### Syntax unification

Version 1.0.0 of Riverpod focused on the unification of the syntax for
interacting with providers.  
Before, Riverpod had many similar yet different syntaxes for reading a provider,
such as `ref.watch(provider)` vs `useProvider(provider)` vs `watch(provider)`.  
With version 1.0.0, only one syntax remains: `ref.watch(provider)`. The
others were removed.

As such:

- `useProvider` is removed in favor of `HookConsumerWidget`.
  Before:

  ```dart
  class Example extends HookWidget {
    @override
    Widget build(BuildContext context) {
      useState(...);
      int count = useProvider(counterProvider);
      ...
    }
  }
  ```

  After:

  ```dart
  class Example extends HookConsumerWidget {
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      useState(...);
      int count = ref.watch(counterProvider);
      ...
    }
  }
  ```

- The prototype of `ConsumerWidget`'s `build` and `Consumer`'s `builder` changed.
  Before:

  ```dart
  class Example extends ConsumerWidget {
    @override
    Widget build(BuildContext context, ScopedReader watch) {
      int count = watch(counterProvider);
      ...
    }
  }

  Consumer(
    builder: (context, watch, child) {
      int count = watch(counterProvider);
      ...
    }
  )
  ```

  After:

  ```dart
  class Example extends ConsumerWidget {
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      int count = ref.watch(counterProvider);
      ...
    }
  }

  Consumer(
    builder: (context, ref, child) {
      int count = ref.watch(counterProvider);
      ...
    }
  )
  ```

- `context.read` is removed in favor of `ref.read`.
  Before:

  ```dart
  class Example extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      SomeButton(
        onPressed: () => context.read(provider.notifier).doSomething(),
      );
    }
  }
  ```

  After:

  ```dart
  class Example extends ConsumerWidget {
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      SomeButton(
        onPressed: () => ref.read(provider.notifier).doSomething(),
      );
    }
  }
  ```

### StateProvider update

[StateProvider] was updated to match [StateNotifierProvider].

Before, doing `ref.watch(StateProvider)` returned a `StateController` instance.
Now it only returns the state of the `StateController`.

To migrate you have a few solutions.  
If your code only obtained the state without modifying it, you can change from:

```dart
final provider = StateProvider<int>(...);

Consumer(
  builder: (context, ref, child) {
    StateController<int> count = ref.watch(provider);

    return Text('${count.state}');
  }
)
```

to:

```dart
final provider = StateProvider<int>(...);

Consumer(
  builder: (context, ref, child) {
    int count = ref.watch(provider);

    return Text('${count}');
  }
)
```

Alternatively you can use the new `StateProvider.state` to keep the old behavior.

```dart
final provider = StateProvider<int>(...);

Consumer(
  builder: (context, ref, child) {
    StateController<int> count = ref.watch(provider.state);

    return Text('${count.state}');
  }
)
```

[statenotifierprovider]: ../providers/state_notifier_provider
[stateprovider]: ../providers/state_provider
[statenotifier]: https://pub.dev/documentation/state_notifier/latest/state_notifier/StateNotifier-class.html
